﻿using BlazorAdmin.Web.Shared.Models;
using BootstrapBlazor.Components;
using Microsoft.AspNetCore.Components;
using Newtonsoft.Json;
using Pangeo.Admin.Models;
using System.IO.Compression;

namespace BlazorAdmin.Web.Shared.Pages.Admin
{
    public partial class UpgradeFiles
    {
        private List<TreeViewItem<FileDirInfo>> FileDirTree { get; set; }

        public FileDirInfo SelectedFileDir { get; set; }

        private string NewDirName { get; set; }

        private DialogOption Option { get; set; }

        /// <summary>
        /// 单个文件最大100MB，超过则无法上传
        /// </summary>
        private long MaxFileLength => 100 * 1024 * 1024;

        protected override async Task OnInitializedAsync()
        {
            await RefreshDirTree();
        }

        /// <summary>
        /// 获取根目录下所有子目录信息
        /// </summary>
        private async Task RefreshDirTree()
        {
            FileDirTree = new List<TreeViewItem<FileDirInfo>>();
            if (Directory.Exists(Consts.UpgradeFilesPath))
            {
                TreeViewItem<FileDirInfo> rootDir;

                // 递归遍根目录
                rootDir = new TreeViewItem<FileDirInfo>(new() { Path = Consts.UpgradeFilesPath });
                RecurseDirGenTree(new DirectoryInfo(Consts.UpgradeFilesPath), rootDir);

                FileDirTree = rootDir.Items;
            }
            else
            {
                Directory.CreateDirectory(Consts.UpgradeFilesPath);

                FileDirTree = new List<TreeViewItem<FileDirInfo>>();
            }
        }

        private async Task GenMD5File()
        {
            if (SelectedFileDir == null || !SelectedFileDir.IsDirectory || !SelectedFileDir.Path.Substring(SelectedFileDir.Path.LastIndexOf("/") + 1).StartsWith("V"))
            {
                MsgService?.Show(new() { Content = "请选择要生成MD5文件的版本号目录" });
                return;
            }

            var fileMD5List = new List<Models.FileMD5Info>();
            RecurseDirGenMD5File(new DirectoryInfo(SelectedFileDir.Path), fileMD5List);

            var json = JsonConvert.SerializeObject(fileMD5List);
            await File.WriteAllTextAsync($"{SelectedFileDir.Path}/MD5.json", json);

            await RefreshDirTree();

            MsgService?.Show(new() { Content = "已生成MD5文件" });
        }

        private void RecurseDirGenMD5File(DirectoryInfo directory, List<Models.FileMD5Info> list)
        {
            // 获取当前目录下的文件
            foreach (var file in directory.GetFiles())
            {
                list.Add(new Models.FileMD5Info()
                {
                    Name = file.Name,
                    Size = file.Length,
                    Hash = BlazorAdmin.Extensions.Utils.GetFileMD5(file.FullName.Replace("\\", "/")),
                    FullName = file.FullName.Substring(file.FullName.IndexOf(Consts.UpgradeFilesPath)).Replace("\\", "/")
                });
            }

            // 遍历当前目录下的子目录
            foreach (var subDir in directory.GetDirectories())
            {
                list.Add(new Models.FileMD5Info()
                {
                    Name = subDir.Name,
                    IsDirectory = true,
                    FullName = subDir.FullName
                });

                RecurseDirGenMD5File(subDir, list);
            }
        }

        private void RecurseDirGenTree(DirectoryInfo directory, TreeViewItem<FileDirInfo> dirData)
        {
            dirData.Text = directory.Name;

            // 获取当前目录下的文件
            foreach (var file in directory.GetFiles())
            {
                dirData.Items.Add(new TreeViewItem<FileDirInfo>(new() { Path = file.FullName.Replace("\\", "/") }) { 
                    Text = $"{file.Name}（ {DescriptFileSize(file.Length)} ，{file.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss")} ）",
                    Icon = "fas fa-file"
                });
            }

            // 遍历当前目录下的子目录
            foreach (var subDir in directory.GetDirectories())
            {
                dirData.Items.Add(new TreeViewItem<FileDirInfo>(new() { Path = subDir.FullName.Replace("\\", "/"), IsDirectory = true }) { 
                    Text = subDir.Name,
                    Icon = "fas fa-folder",
                    ExpandIcon = "fas fa-folder-open"
                });

                RecurseDirGenTree(subDir, dirData.Items[dirData.Items.Count - 1]);
            }
        }

        private string DescriptFileSize(long length)
        {
            if(length < 1024)
                return length + "B";
            else if(length / 1024 < 1024)
                return (length / 1024).ToString("#.##") + "KB";
            else
                return (length / (1024 * 1024)).ToString("#.##") + "MB";
        }

        private async Task OnTreeItemChecked(TreeViewItem<FileDirInfo> items)
        {
            SelectedFileDir = items.Value;
        }

        private async Task DownloadFile()
        {
            if (SelectedFileDir == null)
            {
                MsgService?.Show(new() { Content = "请选择要下载的文件或目录" });
                return;
            }

            var fileName = SelectedFileDir.Path.Substring(SelectedFileDir.Path.LastIndexOf("/") + 1);
            if (SelectedFileDir.IsDirectory) // 如果选择目录，则打包下载
            {
                fileName += ".zip";
                var timeFilePath = $"{Consts.UpgradeFilesPath}/{DateTime.Now.ToString("yyMMddHHmmss")}";
                var zipfilePath = $"{timeFilePath}/{fileName}";

                Directory.CreateDirectory(timeFilePath);

                ZipFile.CreateFromDirectory(SelectedFileDir.Path, zipfilePath);

                if (File.Exists(zipfilePath))
                {
                    using (var stream = new FileStream(zipfilePath, FileMode.Open))
                        await DownloadService?.DownloadFromStreamAsync(fileName, stream);

                    Directory.Delete(timeFilePath, true);
                }
                else
                {
                    MsgService?.Show(new() { Content = "下载失败，无法创建压缩包", Color = Color.Danger });
                }
            }
            else
            {
                using (var stream = new FileStream(SelectedFileDir.Path, FileMode.Open))
                    await DownloadService?.DownloadFromStreamAsync(fileName, stream);
            }
        }

        #region Inject 注入的服务

        [Inject]
        private DialogService? DialogService { get; set; }

        [Inject]
        private MessageService? MsgService { get; set; }

        [Inject]
        private DownloadService? DownloadService { get; set; }

        #endregion
    }
}
